/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef PLPHYSICAL_PAGE_MANAGER_H
#define PLPHYSICAL_PAGE_MANAGER_H

#include <stddef.h>
using namespace std;

#include <tools/PLSingleton.h>
using namespace PLSDK;

/**
 *
 */
class PhysicalPageManager : public PLSingleton<PhysicalPageManager> {
	friend class PLSingleton<PhysicalPageManager>;
public:
	/**
	 * Create all management data but not activate the management.
	 */
	void init();
	/**
	 * Activate the physical memory manager.
	 */
	void activate();
	/**
	 * Set the mem size.
	 *
	 * @param newMemSize The mem size of the system.
	 */
	void setMemSize(uint32_t newMemSize);
	/**
	 * Mark a memory as in use. This function automatically mark maps as in use.
	 *
	 * @param startAdress The start address of the part to mark.
	 * @param length The length of the memory part.
	 */
	void setUsed(uint32_t startAdress, uint32_t length);
	/**
	 * Find the next free map. This uses the m_lastMapTest to start searching.
	 * If we are at the ent we start searching from the beginning again and
	 * if there was no free map we must swap so we return 0 for a not found map.
	 *
	 * @return The position of the next free map or 0 if no free map was found.
	 */
	uint32_t findNextFree();
	/**
	 * Set a page as used page.
	 *
	 * @param page The page to set as used.
	 */
	inline void setUsed(uint32_t page);
	/**
	 * Mark a bit as used.
	 *
	 * @param bit The bit to set.
	 */
	inline void mmap_set(uint32_t bit);
	/**
	 * Mark a bit as unused.
	 *
	 * @param bit The bit to set.
	 */
	inline void mmap_unset(uint32_t bit);
	/**
	 * Is a bit marked as used.
	 */
	inline bool mmap_test(uint32_t bit);
protected:
	/**
	 * Constrcutor.
	 */
	PhysicalPageManager();
private:
	// The memory size in the machine.
	uint32_t m_memSize;
	// The number of memory maps that can be used in the memory.
	uint32_t m_memMapSize;
	// The maps that are mapped.
	uint32_t m_memMapMapped;
	// The length of the map
	uint32_t m_memUsedMapLength;
	// Map with the flags of the used maps.
	uint32_t *m_memUsedMap;
};

void PhysicalPageManager::setUsed(uint32_t page) {
	mmap_set(page);
}

void PhysicalPageManager::mmap_set(uint32_t bit) {
	m_memUsedMap[bit / 32] |= (1 << (bit % 32));
}

void PhysicalPageManager::mmap_unset(uint32_t bit) {
	m_memUsedMap[bit / 32] &= ~(1 << (bit % 32));
}

bool PhysicalPageManager::mmap_test(uint32_t bit) {
	return m_memUsedMap[bit / 32] & (1 << (bit % 32));
}

#endif
